package main

import (
	"errors"
	"fmt"
)

// main
//
//	@Description: 单向链表
func main() {

	head := &HeroNode{
		no:       1,
		name:     "宋江",
		nickname: "及时雨",
	}
	hero3 := &HeroNode{
		no:       3,
		name:     "吴用",
		nickname: "智多星",
	}
	_, _ = InsertHeroNode(head, hero3)

	hero5 := &HeroNode{
		no:       5,
		name:     "卢俊义",
		nickname: "玉麒麟",
	}
	_, _ = InsertHeroNode(head, hero5)

	PrintHeroNode(head)

	fmt.Println()
	heroIn := &HeroNode{
		no:       0,
		name:     "李逵",
		nickname: "黑旋风",
	}
	head, err := InsertHeroNodeByNo(head, heroIn)
	if err != nil {
		fmt.Printf("插入元素失败 ERROR=%v \n", err)
	}
	PrintHeroNode(head)
	//fmt.Println()
	//DeleteHeroNode(head, 2)
	//PrintHeroNode(head)
	//fmt.Println()
	//fmt.Println(FindHeroNode(head, 3))
	//fmt.Println(Size(head))
	//fmt.Println(IsEmpty(head))
}

type HeroNode struct {
	no       int
	name     string
	nickname string
	next     *HeroNode //下一个节点ptr
}

// InsertHeroNode
//
//	@Description: 插入新节点
//	@param head
//	@param hero
func InsertHeroNode(head *HeroNode, hero *HeroNode) (n *HeroNode, err error) {
	cur := head
	for cur != nil {
		//next为空，则说明是最后一个节点
		if cur.next == nil {
			cur.next = hero //将新的节点插入到链表最后
			break
		}
		//否则就将下一个赋值给cur，即往移动一个
		cur = cur.next
	}
	return head, nil
}

// InsertHeroNodeByNo
//
//	@Description: 插入新节点 no从小到大:和当前节点比较:如果当前节点大于插入的节点，则将插入的节点插入到当前节点之前
//	@param head
//	@param hero
//	@return n 新的head,有可能是原来的head，也有可能是新的head
//	@return err
func InsertHeroNodeByNo(head *HeroNode, hero *HeroNode) (n *HeroNode, err error) {
	var prev *HeroNode = nil
	temp := head
	var flag bool
	for temp != nil {
		//如果当前节点大于插入的节点，则将插入的节点插入到当前节点之前
		if temp.no > hero.no {
			if prev == nil {
				hero.next = temp //如果前驱节点为空，将当前节点插入新节点的后面
				head = hero      //新的节点成为新的head
			} else {
				prev.next = hero //将新的节点放在前驱节点后面
				hero.next = temp //将当前节点放到新节点的后面
			}
			flag = true
			break
		} else if temp.no == hero.no {
			return head, errors.New("已有相同no的节点")
		}
		prev = temp      //前驱节点向后移动一位
		temp = temp.next //当前节点向后移动一位
	}

	//如果没有成功插入(说明要插入的元素最大的)，则将新的节点插入到链表最后
	if !flag {
		prev.next = hero
	}
	return head, nil
}

// DeleteHeroNode
//
//	@Description: 删除元素
//	@param head
//	@param no
func DeleteHeroNode(head *HeroNode, no int) {
	var prev *HeroNode = nil //前驱节点
	cur := head              //当前节点
	for cur != nil {
		if cur.no == no {
			if prev == nil {
				head.next = cur.next //如果前驱节点为空，将当前的下一个节点赋值给head
			} else {
				prev.next = cur.next //如果前驱节点不为空，将当前节点的下一个节点赋值给前驱节点的next
			}
		}
		prev = cur     //前驱节点向后移动一位
		cur = cur.next //当前节点向后移动一位
	}
}

// FindHeroNode
//
//	@Description: 查找
//	@param head
//	@param no
//	@return *HeroNode
func FindHeroNode(head *HeroNode, no int) *HeroNode {
	cur := head
	for cur != nil {
		if cur.no == no {
			return cur
		}
		cur = cur.next //当前节点向后移动一位
	}
	return nil
}

// PrintHeroNode
//
//	@Description: 打印
//	@param head
func PrintHeroNode(head *HeroNode) {
	if head == nil {
		return
	}
	cur := head
	for cur != nil {
		fmt.Printf("no=%v name=%v nickname=%v ptr=%p next=%p \n", cur.no, cur.name, cur.nickname, cur, cur.next)
		cur = cur.next //当前节点向后移动一位
	}
}

func Size(head *HeroNode) int {
	if head == nil {
		return 0
	}
	cur := head
	count := 0
	for cur != nil {
		count++
		cur = cur.next //当前节点向后移动一位
	}
	return count
}

func IsEmpty(head *HeroNode) bool {
	return head == nil
}
